package logger

import (
	"fmt"
	"math"
	"strconv"
	"strings"
	"time"

	"gitee.com/wang-xiangyu20000112/vblog/config"
	"go.uber.org/zap"
	"go.uber.org/zap/buffer"
	"go.uber.org/zap/zapcore"
)

// Logger 是全局的日志记录器实例
var ZapLogger *zap.Logger

const (
	green  = "\033[32m" // INFO级别颜色
	yellow = "\033[33m" // WARN级别颜色
	red    = "\033[31m" // ERROR级别颜色
	reset  = "\033[0m"  // 颜色重置
)

var colorMap = map[zapcore.Level]string{
	zapcore.DebugLevel:  "", // DEBUG保持默认色
	zapcore.InfoLevel:   green,
	zapcore.WarnLevel:   yellow,
	zapcore.ErrorLevel:  red,
	zapcore.DPanicLevel: red,
	zapcore.PanicLevel:  red,
	zapcore.FatalLevel:  red,
}

type CustomEncoder struct {
	zapcore.Encoder
}

func (ce *CustomEncoder) EncodeEntry(entry zapcore.Entry, fields []zapcore.Field) (*buffer.Buffer, error) {
	// 使用zap内置的buffer
	buf := buffer.NewPool().Get()

	// 获取颜色控制字符
	colorCode := colorMap[entry.Level]
	resetCode := reset

	// 格式化内容写入buffer
	formatted := fmt.Sprintf("%s[zap] | %s | %s | %s:%d | %s%s",
		colorCode,                   // 颜色开始
		entry.Level.CapitalString(), // 级别名称
		entry.Time.Format("2006-01-02 15:04:05 -0700"),
		entry.Caller.File,
		entry.Caller.Line,
		entry.Message,
		resetCode)

	// 处理额外字段
	if len(fields) > 0 {
		formatted += " -> "
		// 优化后的字段处理逻辑
		var sb strings.Builder
		for i, field := range fields {
			sb.WriteString(fmt.Sprintf("%s:", field.Key))
			switch field.Type {
			case zapcore.StringType:
				sb.WriteString(field.String)
			case zapcore.DurationType:
				sb.WriteString(time.Duration(field.Integer).String())
			case zapcore.Int64Type:
				sb.WriteString(strconv.FormatInt(field.Integer, 10))
			case zapcore.Float64Type:
				sb.WriteString(strconv.FormatFloat(
					math.Float64frombits(uint64(field.Integer)),
					'f', -1, 64))
			case zapcore.BoolType:
				sb.WriteString(strconv.FormatBool(field.Integer == 1))
			default:
				sb.WriteString(fmt.Sprintf("%v", field.Interface))
			}
			formatted += sb.String()
			sb.Reset()
			if i < len(fields)-1 {
				formatted += " | "
			}
		}
	}
	buf.AppendString(formatted + "\n")

	return buf, nil
}

// 通过组合现有Encoder实现其他接口方法（如Clone）
func NewCustomEncoder(cfg zapcore.EncoderConfig) zapcore.Encoder {
	return &CustomEncoder{
		Encoder: zapcore.NewConsoleEncoder(cfg), // 使用JSON Encoder作为基础
	}
}

// InitLogger 初始化 zap 日志记录器并使用自定义的 ConsoleEncoder
func InitZapLogger() error {
	var err error

	err = zap.RegisterEncoder("custom", func(config zapcore.EncoderConfig) (zapcore.Encoder, error) {
		return NewCustomEncoder(config), nil // ✅ 使用工厂函数
	})

	if err != nil {
		panic(err)
	}

	encoderConfig := zap.Config{
		Encoding:    "custom",
		Level:       zap.NewAtomicLevelAt(zap.DebugLevel),
		Development: true, // 使用自定义编码器
		EncoderConfig: zapcore.EncoderConfig{
			MessageKey:    "msg",                     // 日志消息的键名
			LevelKey:      "lvl",                     // 日志级别的键名
			TimeKey:       "ts",                      // 时间戳的键名
			NameKey:       "logger",                  // 日志记录器名称的键名
			CallerKey:     "caller",                  // 调用者信息的键名
			StacktraceKey: "stack",                   // 堆栈跟踪信息的键名
			LineEnding:    zapcore.DefaultLineEnding, // 默认行尾符
			// EncodeLevel:    zapcore.CapitalColorLevelEncoder, // 使用大写带颜色的日志级别
			EncodeTime:     zapcore.ISO8601TimeEncoder,     // 使用 ISO8601 格式的时间戳
			EncodeDuration: zapcore.SecondsDurationEncoder, // 持续时间以秒数表示
			// EncodeCaller:   zapcore.ShortCallerEncoder,       // 缩略路径的调用者信息
		},
		OutputPaths:      []string{"stdout", config.GlobalConfig.Log.FilePath}, // 日志输出到标准输出
		ErrorOutputPaths: []string{"stderr"},                                   // 错误日志输出到标准错误输出
	}

	// 初始化Logger
	ZapLogger, err = encoderConfig.Build()
	if err != nil {
		return err
	}
	ZapLogger.Info("zap logger init success")
	return nil
}

func CloseLogger() {
	_ = ZapLogger.Sync()
}
